package edu.yctc.weblog.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.yctc.weblog.constant.ConstantHolder;
import edu.yctc.weblog.constant.ResultCode;
import edu.yctc.weblog.dao.BlogDAO;
import edu.yctc.weblog.dao.CategoryDAO;
import edu.yctc.weblog.entity.CategoryDO;
import edu.yctc.weblog.entity.PageDO;
import edu.yctc.weblog.entity.ResultDO;
import edu.yctc.weblog.enums.CategoryDeleteStatus;
import edu.yctc.weblog.service.CategoryService;
import edu.yctc.weblog.utils.PageQueryUtil;

@Service("categoryService")
public class CategoryServiceImpl implements CategoryService {

    private final static Logger LOG = LoggerFactory.getLogger("serviceLogger");

    @Resource
    private CategoryDAO categoryDAO;

    @Resource
    private BlogDAO blogDAO;

    @Override
    public ResultDO<PageDO> getCategoryList(PageQueryUtil pageQueryUtil) {
        if (pageQueryUtil.get("start") == null || pageQueryUtil.get("limit") == null) {
            LOG.error("get category list fail, parameter invalid, query args={}", pageQueryUtil);
            return new ResultDO<PageDO>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
        }

        List<CategoryDO> categoryDOList = categoryDAO.getCategoryList(pageQueryUtil);
        int total = categoryDAO.getTotalCategories();
        PageDO pageDO = new PageDO(total, pageQueryUtil.getLimit(), pageQueryUtil.getPage(), categoryDOList);
        return new ResultDO<PageDO>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, pageDO);
    }

    @Override
    @Transactional
    public ResultDO<Void> saveCategory(String name, String icon) {
        if (StringUtils.isBlank(name) || StringUtils.isBlank(icon)) {
            LOG.error("save category fail, parameter invalid, name={}, icon={}", name, icon);
            return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
        }
        CategoryDO categoryDO = categoryDAO.getCategoryDOByName(name);
        if (categoryDO != null) {
            LOG.error("save category fail, category already exist, name={}", name);
            return new ResultDO<>(false, ResultCode.CATEGORY_CATEGORY_ALREADY_EXIST,
                ResultCode.MSG_CATEGORY_CATEGORY_ALREADY_EXIST);
        }
        categoryDO = new CategoryDO();
        categoryDO.setName(name);
        categoryDO.setIcon(icon);
        categoryDO.setRank(1);
        categoryDO.setIsDeleted(CategoryDeleteStatus.UNDELETED);
        categoryDAO.insert(categoryDO);
        return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS);
    }

    @Override
    @Transactional
    public ResultDO<Void> updateCategory(Long id, String name, String icon) {
        if (id < 0 || StringUtils.isBlank(name) || StringUtils.isBlank(icon)) {
            LOG.error("update category fail, parameter invalid, id={}, name={}, icon={}", id, name, icon);
            return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
        }
        CategoryDO categoryDO = categoryDAO.getCategoryDOById(id);
        if (categoryDO != null) {
            categoryDO.setName(name);
            categoryDO.setIcon(icon);
            categoryDAO.update(categoryDO);
        } else {
            LOG.error("update category fail, no such category, id={}, name={}, icon={}", id, name, icon);
            return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR);
        }

        return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS);
    }

    @Override
    @Transactional
    public ResultDO<Void> deleteCategory(Long[] ids) {
        if (ids.length < 1) {
            LOG.error("delete category fail, no category to delete");
            return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
        }
        for (Long id : ids) {
            if (id <= 0) {
                LOG.error("delete category fail, parameter invalid, id={}", id);
                return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID);
            }
        }
        blogDAO.updateBlogCategorys(ConstantHolder.ID_OF_DEFAULT_CATEGORY, ids);
        categoryDAO.deleteBatch(ids);
        LOG.info("delete category success");
        return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS);
    }

    @Override
    public ResultDO<Integer> getTotalCategories() {
        return new ResultDO<Integer>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS,
            categoryDAO.getTotalCategories());
    }

    @Override
    public ResultDO<List<CategoryDO>> getAllCategories() {
        return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, categoryDAO.getCategoryList(null));
    }

}
